home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / SOURCES / STREDITO.C < prev    next >
C/C++ Source or Header  |  1991-12-21  |  11KB  |  356 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * StringEditor - interactive editor for character strings
  25.  */
  26.  
  27. #include <InterViews/bitmap.h>
  28. #include <InterViews/button.h>
  29. #include <InterViews/cursor.h>
  30. #include <InterViews/font.h>
  31. #include <InterViews/painter.h>
  32. #include <InterViews/sensor.h>
  33. #include <InterViews/shape.h>
  34. #include <InterViews/streditor.h>
  35. #include <InterViews/textbuffer.h>
  36. #include <InterViews/textdisplay.h>
  37.  
  38. #include <InterViews/Bitmaps/hand.bm>
  39. #include <InterViews/Bitmaps/handm.bm>
  40. #include <InterViews/Bitmaps/lfast.bm>
  41. #include <InterViews/Bitmaps/lfastm.bm>
  42. #include <InterViews/Bitmaps/rfast.bm>
  43. #include <InterViews/Bitmaps/rfastm.bm>
  44.  
  45. #include <ctype.h>
  46. #include <stdio.h>
  47. #include <string.h>
  48.  
  49. static const int BUFFERSIZE = 1000;
  50.  
  51. StringEditor::StringEditor (
  52.     ButtonState* s, const char* samp, const char* done
  53. ) {
  54.     Init(s, samp, done);
  55. }
  56.  
  57. StringEditor::StringEditor (
  58.     const char* name, ButtonState* s, const char* samp, const char* done
  59. ) {
  60.     SetInstance(name);
  61.     Init(s, samp, done);
  62. }
  63.  
  64. void StringEditor::Init (ButtonState* s, const char* samp, const char* d) {
  65.     SetClassName("StringEditor");
  66.     sample = samp;
  67.     size = BUFFERSIZE;
  68.     buffer = new char[size];
  69.     text = new TextBuffer(buffer, 0, size);
  70.     left = 0;
  71.     right = 0;
  72.     subject = s;
  73.     if (subject != nil) {
  74.         subject->Attach(this);
  75.     }
  76.     done = d;
  77.     display = new TextDisplay();
  78.     display->CaretStyle(NoCaret);
  79.     input = new Sensor();
  80.     input->Catch(KeyEvent);
  81.     input->Catch(DownEvent);
  82.     Message(sample);
  83. }
  84.  
  85. StringEditor::~StringEditor () {
  86.     if (subject != nil) {
  87.         subject->Detach(this);
  88.     }
  89.     delete text;
  90.     delete buffer;
  91.     delete display;
  92. }
  93.  
  94. static Cursor* handCursor;
  95. static Cursor* leftCursor;
  96. static Cursor* rightCursor;
  97.  
  98. void StringEditor::Reconfig () {
  99.     if (handCursor == nil) {
  100.         Bitmap hand(
  101.             hand_bits, hand_width, hand_height, hand_x_hot, hand_y_hot
  102.         );
  103.         Bitmap handmask(hand_mask_bits, hand_mask_width, hand_mask_height);
  104.         Bitmap left(
  105.             lfast_bits, lfast_width, lfast_height, lfast_x_hot, lfast_y_hot
  106.         );
  107.         Bitmap leftmask(lfast_mask_bits, lfast_mask_width, lfast_mask_height);
  108.         Bitmap right(
  109.             rfast_bits, rfast_width, rfast_height, rfast_x_hot, rfast_y_hot
  110.         );
  111.         Bitmap rightmask(rfast_mask_bits, rfast_mask_width, rfast_mask_height);
  112.  
  113.         handCursor = new Cursor(
  114.             &hand, &handmask, output->GetFgColor(), output->GetBgColor()
  115.         );
  116.         leftCursor = new Cursor(
  117.             &left, &leftmask, output->GetFgColor(), output->GetBgColor()
  118.         );
  119.         rightCursor = new Cursor(
  120.             &right, &rightmask, output->GetFgColor(), output->GetBgColor()
  121.         );
  122.     }
  123.  
  124.     Font* f = output->GetFont();
  125.     shape->Rect(f->Width(sample), f->Height());
  126.     shape->Rigid(hfil, hfil, 0, 0);
  127.     display->LineHeight(f->Height());
  128. }
  129.  
  130. void StringEditor::Resize () {
  131.     display->Draw(output, canvas);
  132.     display->Resize(0, 0, xmax, ymax);
  133.     Select(left, right);
  134. }
  135.  
  136. void StringEditor::Redraw (Coord l, Coord b, Coord r, Coord t) {
  137.     display->Draw(output, canvas);
  138.     display->Redraw(l, b, r, t);
  139. }
  140.  
  141. void StringEditor::Message (const char* t) {
  142.     text->Delete(text->BeginningOfText(), text->Length());
  143.     text->Insert(0, t, strlen(t));
  144.     int bol = text->BeginningOfLine(0);
  145.     int eol = text->EndOfLine(0);
  146.     display->Draw(output, canvas);
  147.     display->ReplaceText(0, text->Text(bol, eol), eol - bol);
  148.     Select(eol);
  149. }
  150.  
  151. void StringEditor::Select (int l) {
  152.     Select(l, l);
  153. }
  154.  
  155. void StringEditor::Select (int l, int r) {
  156.     display->Draw(output, canvas);
  157.     int origin = display->Left(0, 0);
  158.     if (display->Left(0, r - 1) < 0) {
  159.         origin += xmax/2 - display->Left(0, r - 1);
  160.     } else if (display->Right(0, r + 1) > xmax) {
  161.         origin += xmax/2 - display->Right(0, r + 1);
  162.     }
  163.     origin = min(0, max(min(0, xmax - display->Width()), origin));
  164.     display->Scroll(0, origin, ymax);
  165.     DoSelect(l, r);
  166. }
  167.  
  168. void StringEditor::DoSelect (int l, int r) {
  169.     display->Draw(output, canvas);
  170.     if (l > r) {
  171.         int tmp = r;
  172.         r = l;
  173.         l = tmp;
  174.     }
  175.     l = max(l, text->BeginningOfLine(left));
  176.     r = min(r, text->EndOfLine(right));
  177.     if (r < left || l > right) {
  178.         if (right > left) {
  179.             display->Style(0, left, 0, right-1, Plain);
  180.         }
  181.         if (r > l) {
  182.             display->Style(0, l, 0, r-1, Reversed);
  183.         }
  184.     } else {
  185.         if (l < left) {
  186.             display->Style(0, l, 0, left-1, Reversed);
  187.         } else if (l > left) {
  188.             display->Style(0, left, 0, l-1, Plain);
  189.         }
  190.         if (r > right) {
  191.             display->Style(0, right, 0, r-1, Reversed);
  192.         } else if (r < right) {
  193.             display->Style(0, r, 0, right-1, Plain);
  194.         }
  195.     }
  196.     left = l;
  197.     right = r;
  198.     if (left == right) {
  199.         display->Caret(0, left);
  200.     } else {
  201.         display->Caret(-1, 0);
  202.     }
  203. }
  204.  
  205. void StringEditor::Edit () {
  206.     Event e;
  207.     e.target = nil;
  208.     e.eventType = EnterEvent;
  209.     Handle(e);
  210. }
  211.  
  212. void StringEditor::Edit (const char* t, int l, int r) {
  213.     Message(t);
  214.     Select(l, r);
  215.     Edit();
  216. }
  217.  
  218. const char* StringEditor::Text () {
  219.     return text->Text();
  220. }
  221.  
  222. boolean StringEditor::HandleChar (char c) {
  223.     if (strchr(done, c) != nil) {
  224.         if (subject != nil) {
  225.             subject->SetValue(c);
  226.         }
  227.         return true;
  228.     } else {
  229.         switch (c) {
  230.           case SEBeginningOfLine:
  231.             Select(text->BeginningOfLine(left));
  232.             break;
  233.           case SEEndOfLine:
  234.             Select(text->EndOfLine(right));
  235.             break;
  236.           case SESelectAll:
  237.             Select(text->BeginningOfText(), text->EndOfText());
  238.             break;
  239.           case SESelectWord:
  240.             Select(
  241.                 text->BeginningOfWord(text->PreviousCharacter(left)), right
  242.             );
  243.             break;
  244.           case SEPreviousCharacter:
  245.             Select(text->PreviousCharacter(left));
  246.             break;
  247.           case SENextCharacter:
  248.             Select(text->NextCharacter(right));
  249.             break;
  250.           case SEDeleteNextCharacter:
  251.             if (left == right) {
  252.                 right = text->NextCharacter(right);
  253.             }
  254.             InsertText("", 0);
  255.             break;
  256.           case SEDeletePreviousCharacter:
  257.           case SEDeletePreviousCharacterAlt:
  258.             if (left == right) {
  259.                 left = text->PreviousCharacter(left);
  260.             }
  261.             InsertText("", 0);
  262.             break;
  263.           default:
  264.             if (!iscntrl(c)) {
  265.                 InsertText(&c, 1);
  266.             }
  267.             break;
  268.         }
  269.         return false;
  270.     }
  271. }
  272.  
  273. void StringEditor::InsertText (const char* t, int len) {
  274.     display->Draw(output, canvas);
  275.     if (left != right) {
  276.         text->Delete(left, right-left);
  277.         display->DeleteText(0, left, right-left);
  278.     }
  279.     text->Insert(left, t, len);
  280.     display->InsertText(0, left, t, len);
  281.     int l = left;
  282.     while (len > 0) {
  283.         l = text->NextCharacter(l);
  284.         --len;
  285.     }
  286.     Select(l);
  287. }
  288.  
  289. void StringEditor::Handle (Event& e) {
  290.     boolean done = false;
  291.     display->Draw(output, canvas);
  292.     display->CaretStyle(BarCaret);
  293.     do {
  294.         switch (e.eventType) {
  295.           case KeyEvent:
  296.             if (e.len != 0) {
  297.                 done = HandleChar(e.keystring[0]);
  298.             }
  299.             break;
  300.           case DownEvent:
  301.             if (e.target == this) {
  302.                 int origin = display->Left(0, 0);
  303.                 int width = display->Width();
  304.                 if (e.button == LEFTMOUSE) {
  305.                     int start = display->LineIndex(0, e.x);
  306.                     do {
  307.                         if (e.x < 0) {
  308.                             origin = min(0, origin - e.x);
  309.                         } else if (e.x > xmax) {
  310.                             origin = max(xmax - width, origin - (e.x - xmax));
  311.                         }
  312.                         display->Scroll(0, origin, ymax);
  313.                         DoSelect(start, display->LineIndex(0, e.x));
  314.                         Poll(e);
  315.                     } while (e.leftmouse);
  316.                 } else if (e.button == MIDDLEMOUSE) {
  317.                     Cursor* origCursor = GetCursor();
  318.                     SetCursor(handCursor);
  319.                     int x = e.x;
  320.                     do {
  321.                         origin += e.x - x;
  322.                         origin = min(0, max(min(0, xmax - width), origin));
  323.                         display->Scroll(0, origin, ymax);
  324.                         x = e.x;
  325.                         Poll(e);
  326.                     } while (e.middlemouse);
  327.                     SetCursor(origCursor);
  328.                 } else if (e.button == RIGHTMOUSE) {
  329.                     Cursor* origCursor = GetCursor();
  330.                     int x = e.x;
  331.                     do {
  332.                         origin += x - e.x;
  333.                         origin = min(0, max(min(0, xmax - width), origin));
  334.                         display->Scroll(0, origin, ymax);
  335.                         if (e.x - x < 0) {
  336.                             SetCursor(leftCursor);
  337.                         } else {
  338.                             SetCursor(rightCursor);
  339.                         }
  340.                         Poll(e);
  341.                     } while (e.rightmouse);
  342.                     SetCursor(origCursor);
  343.                 }
  344.             } else {
  345.                 UnRead(e);
  346.                 done = true;
  347.             }
  348.             break;
  349.         }
  350.         if (!done) {
  351.             Read(e);
  352.         }
  353.     } while (!done);
  354.     display->CaretStyle(NoCaret);
  355. }
  356.